package com.zhiche.lisa.bms.service.activiti.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.lisa.bms.enums.ActivitiEnum;
import com.zhiche.lisa.bms.pojo.vo.activiti.HistoryTask;
import com.zhiche.lisa.bms.service.activiti.ActivitiCommonService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author linbao
 * @date 2018-10-16
 */
@Service
@Slf4j
public class ActivitiCommonServiceImpl implements ActivitiCommonService {

	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	private TaskService taskService;

	@Autowired
	private HistoryService historyService;


	/**
	 * 启动流程, 根据指定名
	 *
	 * @param workFlowName
	 * @return
	 * @throws Exception
	 */
	@Override
	public String startWorkFlowCommon(String workFlowName) throws Exception {
		return runtimeService.startProcessInstanceByKey(workFlowName).getId();
	}

	/**
	 * 报价单启动流程
	 *
	 * @throws Exception
	 */
	@Override
	public String startWorkFlow(String type) throws Exception {
		Map<String, Object> map = Maps.newHashMap();
		map.put("type", type);
		return runtimeService.startProcessInstanceByKey(ActivitiEnum.ACTIVITI_NAME.getCode()).getId();
	}

	/**
	 * 启动支付申请单审核
	 *
	 * @return
	 * @throws Exception
	 */
	@Override
	public String startPayApplyWorkFlow(Map<String, Object> map) throws Exception {
		return runtimeService.startProcessInstanceByKey(ActivitiEnum.ACTIVITI_PAY_APPLY_NAME.getCode(), map).getId();
	}

    /**
     * 启动临时报价单审批流程
     *
     * @return
     * @throws Exception
     */
    @Override
    public String startTempQuoteWorkFlow() throws Exception {
        return runtimeService.startProcessInstanceByKey(ActivitiEnum.ACTIVITI_TEMP_QUOTE_NAME.getCode()).getId();
    }

    /**
	 * 获取当前任务
	 *
	 * @param processId
	 * @return
	 * @throws Exception
	 */
	@Override
	public Task getCurrentTaskByProcessId(String processId) throws Exception {
		log.info("获取当前任务 processId: {}", processId);
		return taskService.createTaskQuery().processInstanceId(processId).singleResult();
	}

	/**
	 * 根据id获取流程
	 *
	 * @param taskId
	 * @return
	 * @throws Exception
	 */
	@Override
	public Task getTaskByTaskId(String taskId) throws Exception {
		return taskService.createTaskQuery().taskId(taskId).singleResult();
	}

	/**
	 * 获取任务
	 *
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Task> getTaskList(String assignee) throws Exception {
		log.info("当前任务查询: assignee {} ", assignee);
		return taskService.createTaskQuery().taskAssignee(assignee).orderByTaskCreateTime().asc().list();
	}

	/**
	 * 查询当前待审核的id
	 *
	 * @param assignee
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<String> getCurrntUserTaskId(String assignee) throws Exception {
		log.info("当前任务查询: assignee {} ", assignee);
		List<Task> taskList = getTaskList(assignee);
		if (CollectionUtils.isNotEmpty(taskList)) {
			List<String> taskIdList = Lists.newArrayList();
			taskList.forEach(task -> {
				taskIdList.add(task.getId());
			});
			return taskIdList;
		}
		return null;
	}

	/**
	 * 完成
	 *
	 * @param taskId
	 * @throws Exception
	 */
	@Override
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void taskComplete(String taskId, Map<String, Object> map) throws Exception {
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		log.info("当前流程节点：{}, Assignee：{}", task.getName(), task.getAssignee());
		taskService.complete(task.getId(), map);
	}

	/**
	 * 完成
	 *
	 * @param taskId
	 * @throws Exception
	 */
	@Override
	public void taskComplete(String taskId) throws Exception {
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		log.info("当前流程节点：{}, Assignee：{}", task.getName(), task.getAssignee());
		taskService.complete(task.getId());
	}

	/**
	 * 查询审批历史
	 *
	 * @param pid
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<HistoryTask> queryActivitiHistoryTaskList(String pid) throws Exception {
		if (StringUtils.isNotBlank(pid)) {
			List<HistoryTask> historyTaskList = Lists.newArrayList();
			List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
					.processInstanceId(pid)
					.orderByHistoricActivityInstanceStartTime().asc().list();
			if (CollectionUtils.isNotEmpty(list)) {
				list.forEach(history -> {
					if (ActivitiEnum.ACTIVITI_USER_TASK_TYPE.equals(history.getActivityType())) {
						HistoryTask historyTask = new HistoryTask();
						if (history.getEndTime() != null) {
							historyTask.setConfirmDate(history.getEndTime());
							if (StringUtils.isNotBlank(history.getDeleteReason())) {
								historyTask.setTaskAssignee(String.format(ActivitiEnum.ADUST_FAIL, history.getActivityName(), history.getDeleteReason()));
							} else {
								historyTask.setTaskAssignee(String.format(ActivitiEnum.HISTORY_ASSIGNEE, history.getActivityName()));
							}
						} else {
							historyTask.setTaskAssignee(String.format(ActivitiEnum.ASSIGNEE_FORM, history.getActivityName()));
						}
						historyTask.setActivityId(history.getActivityId());
						historyTaskList.add(historyTask);
					}
				});
			}
			return historyTaskList;
		}
		return null;
	}

	/**
	 * 删除任务
	 *
	 * @param pid
	 * @throws Exception
	 */
	@Override
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void deleteActivitiByProcessId(String pid, String reason) throws Exception {
		// runtimeService.ac
		Task task = taskService.createTaskQuery().processInstanceId(pid).singleResult();
		if (task != null) {
			runtimeService.deleteProcessInstance(pid, reason);
		}
	}
}
